package aliyunpan

import (
	"bytes"
	"center-platform/utils"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"time"
)

type Items struct {
	Name      string `json:"name"`
	Thumbnail string `json:"thumbnail"`
	Type      string `json:"type"`
	Category  string `json:"category"`
	Hidden    bool   `json:"hidden"`
	Status    string `json:"status"`
	//Description        interface{} `json:"description"`
	//Meta               interface{} `json:"meta"`
	Url     string `json:"url"`
	Size    int    `json:"size"`
	Starred bool   `json:"starred"`
	//Location           interface{} `json:"location"`
	//Deleted            interface{} `json:"deleted"`
	//Channel            interface{} `json:"channel"`
	//UserTags           interface{} `json:"user_tags"`
	MimeType      string `json:"mime_type"`
	ParentFileId  string `json:"parent_file_id"`
	DriveId       string `json:"drive_id"`
	FileId        string `json:"file_id"`
	FileExtension string `json:"file_extension"`
	//RevisionId         interface{} `json:"revision_id"`
	ContentHash     string `json:"content_hash"`
	ContentHashName string `json:"content_hash_name"`
	EncryptMode     string `json:"encrypt_mode"`
	DomainId        string `json:"domain_id"`
	//DownloadUrl        interface{} `json:"download_url"`
	//UserMeta           interface{} `json:"user_meta"`
	//ContentType        interface{} `json:"content_type"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
	//LocalCreatedAt     interface{} `json:"local_created_at"`
	//LocalModifiedAt    interface{} `json:"local_modified_at"`
	//TrashedAt          interface{} `json:"trashed_at"`
	PunishFlag int `json:"punish_flag"`
	//VideoMediaMetadata interface{} `json:"video_media_metadata"`
	//ImageMediaMetadata struct {
	//	AddressLine     interface{} `json:"address_line"`
	//	City            interface{} `json:"city"`
	//	Country         interface{} `json:"country"`
	//	District        interface{} `json:"district"`
	//	Faces           interface{} `json:"faces"`
	//	FacesThumbnail  interface{} `json:"faces_thumbnail"`
	//	Height          interface{} `json:"height"`
	//	ImageQuality    interface{} `json:"image_quality"`
	//	Location        interface{} `json:"location"`
	//	Province        interface{} `json:"province"`
	//	StoryImageScore interface{} `json:"story_image_score"`
	//	Time            interface{} `json:"time"`
	//	Township        interface{} `json:"township"`
	//	Width           interface{} `json:"width"`
	//	Exif            string      `json:"exif"`
	//} `json:"image_media_metadata"`
	//PlayCursor           interface{} `json:"play_cursor"`
	//VideoPreviewMetadata interface{} `json:"video_preview_metadata"`
	//StreamsInfo          interface{} `json:"streams_info"`
	//IdPath               interface{} `json:"id_path"`
	//NamePath             interface{} `json:"name_path"`
}

type List struct {
	Files      []Items `json:"items"`
	NextMarker string  `json:"next_marker"`
}

type SearchListReq struct {
	DriveId        string `json:"drive_id"`
	ParentFileId   string `json:"parent_file_id"`
	Limit          int    `json:"limit,omitempty"`
	Marker         string `json:"marker,omitempty"`
	OrderBy        string `json:"order_by,omitempty"`
	OrderDirection string `json:"order_direction,omitempty"`
	Type           string `json:"type,omitempty"`
}

type SearchItemReq struct {
	DriveId string `json:"drive_id"`
	FileId  string `json:"file_id"`
}

type CreateFileReq struct {
	DriveId       string `json:"drive_id"`
	ParentFileId  string `json:"parent_file_id"`
	Name          string `json:"name"`
	Type          string `json:"type"`
	CheckNameMode string `json:"check_name_mode,omitempty"`
}
type CreateResp struct {
	Type         string `json:"type"`
	ParentFileId string `json:"parent_file_id"`
	DriveId      string `json:"drive_id"`
	FileId       string `json:"file_id"`
	RevisionId   string `json:"revision_id"`
	EncryptMode  string `json:"encrypt_mode"`
	DomainId     string `json:"domain_id"`
	FileName     string `json:"file_name"`
	UploadId     string `json:"upload_id"`
	Location     string `json:"location"`
	RapidUpload  bool   `json:"rapid_upload"`
	PartInfoList []struct {
		PartNumber  int    `json:"part_number"`
		PartSize    int    `json:"part_size"`
		UploadUrl   string `json:"upload_url"`
		ContentType string `json:"content_type"`
	} `json:"part_info_list"`
}

type CompleteReq struct {
	DriveId  string `json:"drive_id"`
	FileId   string `json:"file_id"`
	UploadId string `json:"upload_id"`
}

type MoveFileReq struct {
	DriveId        string `json:"drive_id"`
	FileId         string `json:"file_id"`
	ToParentFileId string `json:"to_parent_file_id"`
	CheckNameMode  string `json:"check_name_mode,omitempty"`
	NewName        string `json:"new_name,omitempty"`
}

type MoveFileResp struct {
	DiveId      string `json:"drive_id"`
	FileId      string `json:"file_id"`
	AsyncTaskId string `json:"async_task_id"`
	Exist       bool   `json:"exist"`
}

func (a *AliYunPan) GetFileList(param SearchListReq) List {
	url := Host + "/adrive/v1.0/openFile/list"
	body, err := json.Marshal(param)
	if err != nil {
		return List{}
	}
	token, _ := a.GetAccessToken("")
	httpServer := utils.InitHttp()
	httpServer.SetAuth(token)
	head := map[string]string{
		"Content-Type": "application/json",
	}
	res, err := httpServer.Do("POST", url, body, true, head)
	var result List
	err = json.Unmarshal(res, &result)
	if err != nil {
		fmt.Println("列表err", err)
		return List{}
	}
	return result
}

func (a *AliYunPan) GetFile(param SearchItemReq) Items {
	url := Host + "/adrive/v1.0/openFile/get"
	body, err := json.Marshal(param)
	if err != nil {
		return Items{}
	}
	token, _ := a.GetAccessToken("")
	httpServer := utils.InitHttp()
	httpServer.SetAuth(token)
	head := map[string]string{
		"Content-Type": "application/json",
	}
	res, err := httpServer.Do("POST", url, body, true, head)
	var result Items
	err = json.Unmarshal(res, &result)
	if err != nil {
		fmt.Println("列表err", err)
		return Items{}
	}
	return result
}

func (a *AliYunPan) Upload(param CreateFileReq, filepath string) string {
	//1.获取上传地址
	createUrl := Host + "/adrive/v1.0/openFile/create"
	body, err := json.Marshal(param)
	if err != nil {
		fmt.Println(err)
		return ""
	}
	token, _ := a.GetAccessToken("")
	httpServer := utils.InitHttp()
	httpServer.SetAuth(token)
	head := map[string]string{
		"Content-Type": "application/json",
	}
	res, err := httpServer.Do("POST", createUrl, body, true, head)
	var result CreateResp
	err = json.Unmarshal(res, &result)
	if err != nil {
		fmt.Println("创建文件失败", err)
	}
	//2.上传文件
	file, err := os.Open(filepath)
	if err != nil {
		fmt.Println("打开文件失败", err)
		return ""
	}
	defer file.Close()
	uploadUrl := result.PartInfoList[0].UploadUrl
	var requestBody bytes.Buffer
	_, err = io.Copy(&requestBody, file)
	if err != nil {
		log.Fatalf("读取文件失败: %v", err)
		return ""
	}

	// 创建请求
	req, err := http.NewRequest("PUT", uploadUrl, &requestBody)
	if err != nil {
		log.Fatalf("创建请求失败: %v", err)
		return ""
	}
	// 创建HTTP客户端并发送请求
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Fatalf("执行请求失败: %v", err)
		return ""
	}
	defer resp.Body.Close()

	// 读取响应
	_, err = io.ReadAll(resp.Body)
	if err != nil {
		log.Fatalf("读取响应失败: %v", err)
		return ""
	}
	if resp.StatusCode == 200 {
		//3标记上传成功
		completeUrl := Host + "/adrive/v1.0/openFile/complete"
		completeBody, err := json.Marshal(CompleteReq{
			DriveId:  result.DriveId,
			FileId:   result.FileId,
			UploadId: result.UploadId,
		})
		if err != nil {
			fmt.Println(err)
			return ""
		}
		_, err = httpServer.Do("POST", completeUrl, completeBody, true, head)
		if err != nil {
			fmt.Println("上传失败", err)
			return ""
		}
		return result.FileId
	} else {
		return ""
	}
}

func (a *AliYunPan) MoveFile(param MoveFileReq) (*MoveFileResp, error) {
	url := Host + "/adrive/v1.0/openFile/move"
	body, err := json.Marshal(param)
	if err != nil {
		fmt.Println(err)
		return nil, err
	}
	token, _ := a.GetAccessToken("")
	httpServer := utils.InitHttp()
	httpServer.SetAuth(token)
	head := map[string]string{
		"Content-Type": "application/json",
	}
	fmt.Println("body", string(body))
	res, err := httpServer.Do("POST", url, body, true, head)
	var result MoveFileResp
	err = json.Unmarshal(res, &result)
	if err != nil {
		fmt.Println("移动文件失败", err)
	}
	return &result, nil
}
